#pragma once
#pragma warning( disable : 4244 4800)
#include <iostream>
#include <List>
using namespace std;


/*Declarations*/
class Meeting;
class Day;
class Calendar;
enum CalendarError;

#define MEETING 1
#define DAY 1
#define CALENDAR 1

class Calendar {
public:
	Calendar(int nof_days);
	virtual ~Calendar();
	
	virtual CalendarError createMeeting(const char *subject, float startTime, float endTime, int day, /*out*/const Meeting *&meeting);
	virtual CalendarError getMeeting(const char *subject, float startTime, float endTime, int day, /*out*/ const Meeting *&meeting);
	virtual CalendarError addMeeting(const Meeting &meeting);
	virtual CalendarError deleteMeeting(const Meeting &meeting);
	virtual CalendarError findMeetingStartingAt(float startTime, /*out*/const Meeting **meetings, int maxNofMeetings,/*out*/ int &nofMeetings) const;
	virtual CalendarError moveMeeting(const Meeting &meeting, float startTime, float endTime, int day, /*out*/ const Meeting *&newMeeting);
	virtual CalendarError printAll() const;
	virtual CalendarError clean();
	virtual int whoAmI() const;

protected:
	virtual CalendarError createDays(int nof_days);
	CalendarError getDay(int day_num, /*out*/ Day *&day);

private:
	Day *days;
	int nof_days;
};

class Day {
public:
	Day();
	Day(int dayNumber);
	Day(Calendar &calendar, int dayNumber);
	virtual ~Day();
	
	virtual CalendarError addMeeting(const Meeting &meeting);
	virtual CalendarError deleteMeeting(const Meeting &meeting);
	virtual CalendarError findMeetingStartingAt(float startTime,/*out*/const Meeting **meetings, int maxNofMeetings,/*out*/int &howMany) const;
	virtual CalendarError findMeetingsDuring(float startTime, float endTime, /*out*/ const Meeting **meetings,int maxNofMeetings, /*out*/ int &howMany) const;
	virtual CalendarError findMeetingBySubject(const char* subject, /*out*/ const Meeting **meetings, int maxNofMeetings,/*out*/ int &howMany) const;
	virtual CalendarError findMeeting(const char *subject, int day, float startTime, float endTime,const Meeting *&meeting) const;
	virtual CalendarError getDayNumber(int &dayOfWeek) const;
	virtual CalendarError printAll() const;
	virtual CalendarError clean();
	virtual int whoAmI() const;

	virtual void operator= (const Day& day);
	virtual bool operator== (const Day& day) const;	

protected:
	virtual CalendarError isOverlap(const Meeting &meeting, /*out*/ bool &status) const;  
	virtual CalendarError getCalendar(/*out*/ Calendar *&calendar) const;

private:
	Calendar *calendar;
	int dayNumber;
	list<const Meeting *> meetingsList;
};

class Meeting {
public:
	Meeting();
	Meeting(float startTime, float endTime, const char* subject);
	Meeting(float startTime, float endTime, const char* subject, Day &day, Calendar &calendar);
	virtual ~Meeting();

	virtual CalendarError getStartTime(float &startTime) const;
	virtual CalendarError getEndTime(float &endTime) const;
	virtual CalendarError getSubject(const char *&subject) const;
	virtual CalendarError getDay(/*out*/ Day *&day) const;
	virtual CalendarError printAll() const;
	virtual CalendarError isOverlap(const Meeting &meeting, bool &status) const;
	virtual int whoAmI() const;

	virtual void operator= (const Meeting& meeting);
	virtual bool operator== (const Meeting& meeting) const;

protected:

	virtual CalendarError setStartTime(float startTime);
	virtual CalendarError setEndTime(float endTime);
	virtual CalendarError setSubject(const char *subject);
	virtual CalendarError setDay(Day &day);
	
private:
	Calendar *calendar;
	Day *day;
	float startTime;
	float endTime;
	const char* subject;
};

enum CalendarError {
	CALENDAR_ERROR_NONE,
	CALENDAR_ERROR_FAIL,
	CALENDAR_ERROR_NOT_EXIST,
	CALENDAR_ERROR_ALREADY_EXIST,
	CALENDAR_ERROR_PARAM,
	CALENDAR_ERROR_OVERLAP,
	CALENDAR_ERROR_MEMORY
};